package com.demoworld;

/**
 * Created by francis on 2017/7/5.
 * 该类只是熟悉hashmap原理， 不能直接使用
 */
public class JHashMap implements IMap {
    private static final int defaultLength = 2;

    public JHashMap() {
        this.length = 0;
        this.data = new JHashMapItem[defaultLength];
    }

    private JHashMapItem[] data;
    private int length;

    @Override
    public void put(String key, int value) {
        if (key == null || key.length() == 0) {
            return;
        }
        JHashMapItem node = new JHashMapItem(key, value, null);
        this.length++;
        int index = getIndexByKey(key);
        if (index > data.length - 1) {
            scanlMap();
        }

        JHashMapItem tmpTheItem = data[index];
        if (tmpTheItem != null) {//发生了碰撞
            JHashMapItem tmp = data[index];
            data[index] = node;
            node.next = tmp;
            return;
        }
        data[index] = node;
    }

    @Override
    public int get(String key) {
        if (this.isEmpty()) {
            return -1;//为了测试方便， -1标示没有数据了
        }
        int index = getIndexByKey(key);
        if (index > this.length - 1) {
            return -2;
        }
        JHashMapItem tmpNode = getInLinkedList(data[index], key);
        if (tmpNode == null) {
            return -2;//没有找到key
        }
        return tmpNode.value;
    }

    //遍历单链表
    private JHashMapItem getInLinkedList(JHashMapItem node, String key) {
        if (node == null || key == null || key.length() == 0) {
            return null;
        }
        if (node.key.equalsIgnoreCase(key)) {
            return node;
        }
        if (node.next == null) {
            return null;
        }
        return this.getInLinkedList(node.next, key);
    }

    //删除单链表中的一个node
    private JHashMapItem removeInLinkedList(JHashMapItem pre, JHashMapItem current, String key) {
        if (pre == null || key == null || key.length() == 0) {
            return null;
        }
        if (current == null) {
            return null;
        }
        if (current.key.equalsIgnoreCase(key)) {
            pre.next = current.next;
            return current;
        }
        return this.removeInLinkedList(current, current.next, key);
    }

    @Override
    public int size() {
        return this.length;
    }

    @Override
    public int remove(String key) {
        if (key == null || key.isEmpty()) {
            return -2;
        }
        int index = getIndexByKey(key);
        if (index < this.length) {//
            JHashMapItem node = this.data[index];
            if (node.key.equalsIgnoreCase(key)) {
                this.data[index] = node.next;
                this.length--;
                return node.value;//单链表第一个node就是需要找的key
            }
            node = this.removeInLinkedList(node, node.next, key);
            if (node != null) {
                this.length--;
                return node.value;
            }
        }
        return -3;
    }

    @Override
    public boolean isEmpty() {
        return this.length == 0;
    }

    public int getIndexByKey(String key) {
        return hash(key) & (this.data.length - 1);
    }

    public static final int hash(String key) {
        int h = 0;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> defaultLength);
    }

    private synchronized void scanlMap() {
        JHashMapItem[] tmpData = new JHashMapItem[data.length * 2];
        for (int i = 0; i <= data.length - 1; i++) {
            tmpData[i] = data[i];
        }
        data = tmpData;
    }
}